﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\DataTypes\EnList.cs
 * Description  :      A clonable list
 * Change log   :     -2011: First version (originally, it was part of SimGine library)
 * To Do        :
 ************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections;
using SMLib.Base;

namespace SMLib.DataTypes
{
    /// <summary>
    /// An list of objects
    /// </summary>
    /// <typeparam name="T">Type of elements</typeparam>
    public class EnList<T> :
        List<T>,
        IStateVariable
    {
        //List<T> lst;

        /// <summary>
        /// Constructor
        /// <remarks>Type of T can be primitive, enum, string or it should implement the interface IStateVariable</remarks>
        /// </summary>
        public EnList()
        {
            if (!(typeof(T).IsPrimitive || (typeof(T) == typeof(string)) || (typeof(T).IsEnum)
                || (typeof(T).GetInterface(typeof(IStateVariable).FullName) != null)))
                throw new Exception("The type of T in EnQueue<T> should be builtin, string or IStateVariable!");

            //lst = new List<T>();
        }

        /// <summary>
        /// Convert a list to string (for presentation, e.g., in user interface)
        /// </summary>
        /// <returns>the string valued of this list</returns>
        public override string ToString()
        {
            string st = "{";
            for (int i = 0; i < Count; i++)
                st += ((i > 0) ? "," : "") + this[i].ToString();
            st += "}";
            return st;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        ///// <summary>
        ///// Number of objects in the list
        ///// </summary>
        //public int Count
        //{
        //    get
        //    {
        //        return lst.Count;
        //    }
        //}

        ///// <summary>
        ///// Add an item to list
        ///// </summary>
        ///// <param name="item"></param>
        //public void Add(T item)
        //{
        //    lst.Add(item);
        //}

        /// <summary>
        /// Add an item in the begining of list
        /// </summary>
        /// <param name="item">the item to be added</param>
        public void AddFirst(T item)
        {
            Insert(0, item);
        }

        ///// <summary>
        ///// Remove the first occorance
        ///// </summary>
        ///// <param name="item">the item to be removed</param>
        ///// <returns>true if the item was in the list and removed, false if not</returns>
        //public bool Remove(T item)
        //{
        //    return lst.Remove(item);
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="i"></param>
        //public void RemoveAt(int i)
        //{
        //    if (0 <= i && i < lst.Count)
        //        lst.RemoveAt(i);
        //    else
        //        throw new Exception("Index out of range in EnList.RemoveAt!");
        //}

        //public void Clear()
        //{
        //    lst.Clear();
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <returns></returns>
        //public IEnumerator GetEnumerator()
        //{
        //    return new ListEnumerator<T>(lst);
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="item"></param>
        //public bool Contains(T item)
        //{
        //    return lst.Contains(item);
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            if (this.GetType() != obj.GetType())
                return false;
            EnList<T> secondobj = obj as EnList<T>;
            if (this.Count != secondobj.Count)
                return false;
            for (int i = 0; i < Count; i++)
            {
                if (!this[i].Equals(secondobj[i]))
                    return false;
            }
            return true;
        }

        //public T this[int index1]
        //{
        //    get
        //    {
        //        return lst[index1];
        //    }
        //    set
        //    {
        //        lst[index1] = value;
        //    }
        //}

        //public override int GetHashCode()
        //{
        //    //To Do:[implement this function]
        //    return base.GetHashCode();
        //}

        //Check it!
        public object Clone()
        {
            EnList<T> obj = new EnList<T>();
            if ((typeof(T)).IsPrimitive || typeof(T).IsEnum || typeof(T) == typeof(string))
            {
                for (int i = 0; i < Count; i++)
                    obj.Add(this[i]);
            }
            else if (typeof(T) is ICloneable)
            {
                for (int i = 0; i < Count; i++)
                    obj.Add((T)(((ICloneable)this[i]).Clone()));
            }
            return obj;
        }

        #region IState Members


        public object[] Fields
        {
            get { return null; }
        }

        public string GetLocationName(int locationId)
        {
            if (locationId == 0)
                return "No-Name";
            else
                return null;
        }

        public int LocationValuesCount
        {
            get { return 1; }
        }

        public object GetLocation(int locationId)
        {
            if (locationId == 0)
                return this;
            else
                return null;
        }

        #endregion

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj.Equals(this))
                return 0;
            else
                return -1;
        }

        #endregion
    }
}
